package com.google.code.jtasks.model;

import com.google.code.jtasks.model.IMappedTask.ITaskComment;

/**
 * Represents a field/property of {@link IMappedTask}s and their component objects, e.g. {@link ITaskComment}.
 * 
 * @param <O>
 *            the type of the "owner" class: the class that this {@link ITaskProperty} is contained in
 */
public interface ITaskProperty<O>
{
	/*
	 * Design note: Unfortunately, it's not practical to have a generic type parameter for the #getValue(...)
	 * method. Most implementations of this class will be in enums, and all entries in an enum must have the
	 * same type parameters. In addition, leaving the extra type parameter off makes it easier to work with
	 * TaskPropertyValue instances.
	 */

	/**
	 * Returns the name of this {@link ITaskProperty}, which must be unique within its owner class.
	 * 
	 * @return the name of this {@link ITaskProperty}, which must be unique within its owner class
	 */
	public String getName();

	/**
	 * Returns <code>true</code> if the {@link IMappedTask} (or component object, e.g. {@link ITaskComment})
	 * is not required to implement this {@link ITaskProperty}, or <code>false</code> if this
	 * {@link ITaskProperty} must be implemented. Optional {@link ITaskProperty}s that are not implemented
	 * will throw {@link UnsupportedTaskPropertyException}s if accessed.
	 * 
	 * @return <code>true</code> if the {@link IMappedTask} (or component object, e.g. {@link ITaskComment})
	 *         is not required to implement this {@link ITaskProperty}, or <code>false</code> if this
	 *         {@link ITaskProperty} must be implemented
	 */
	public boolean isOptional();

	/**
	 * Returns the {@link Class} of this {@link ITaskProperty}'s values.
	 * 
	 * @return the {@link Class} of this {@link ITaskProperty}'s values
	 */
	public Class<?> getValueType();

	/**
	 * Returns the value for this {@link ITaskProperty} for the given owner class instance.
	 * 
	 * @param owner
	 *            the instance of the owner class to get the {@link ITaskProperty} value for
	 * @return the value for this {@link ITaskProperty} for the given owner class instance
	 * @throws UnsupportedTaskPropertyException
	 *             An {@link UnsupportedTaskPropertyException} will be thrown if the {@link IMappedTask} (or
	 *             component object, e.g. {@link ITaskComment}) implementation does not support this
	 *             {@link ITaskProperty}. Should only be the case if {@link #isOptional()} is
	 *             <code>true</code>.
	 */
	public Object getValue(O owner) throws UnsupportedTaskPropertyException;
}
